﻿using Bridge.System.Domain;
using Bridge.Shared.Extensions;
using Bridge.Shared.Models;
using Mapster;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using Roles;
using Roles.Input;
using Roles.Output;
using System;
using System.Collections.Generic;
using System.Formats.Asn1;
using System.Linq;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using Users;
using Volo.Abp.Application.Services;
using Volo.Abp.Data;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Identity;
using IdentityRole = Volo.Abp.Identity.IdentityRole;


namespace Bridge.System.Application
{
    public class RoleService : ApplicationService, IRoleService
    {
         IRepository<IdentityRole, Guid> _roleRepository;
        private IdentityRoleManager _roleManager;
        private IdentityUserManager _userManager;
        private readonly IRepository<RoleMenu, Guid> _rolemenuRepository;
        private readonly  IRepository<Menu, Guid> _menuRepository;
        public RoleService( IRepository<IdentityRole, Guid> roleRepository, IdentityRoleManager roleManager, IdentityUserManager userManager, IRepository<RoleMenu, Guid> rolemenuRepository, IRepository<Menu, Guid> menuRepository)
        {
            this._roleRepository = roleRepository;
            _roleManager = roleManager;
            _userManager = userManager;
            _rolemenuRepository = rolemenuRepository;
            _menuRepository = menuRepository;
        }
       

        /// <summary>
        /// 给角色分配置菜单
        /// </summary>
        /// <param name="Input"></param>
        /// <returns></returns>
        /// <exception cref="ArgumentException"></exception>
        public async Task<ResponseResult> AddMenuForRolse(AddMenuForRolseInput input)
        {
            var role =await _roleManager.GetByIdAsync(input.Id);
            if (role == null)
            {
                throw new ArgumentException("角色不存在！");
            }
            
            var roleMenus = (await _rolemenuRepository.GetQueryableAsync()).Where(a=>a.RoleId == role.Id).Select(a=>a.MenuId).ToList();

            var oldMenuList = await _menuRepository.GetListAsync(a => roleMenus.Contains(a.Id));

            var newMenuList = await _menuRepository.GetListAsync(a => input.MenuIds.Contains(a.Id));
          

            //取两集合的交集
            var allMenu = oldMenuList.Intersect(newMenuList).Select(a=>a.Id).ToList();

            //要删除的:旧菜单中有，但新菜单中没有的
            var deleMenu = oldMenuList.Where(a => !allMenu.Contains(a.Id)).Select(a=>a.Id).ToList();

            //要新增的：旧菜单中没有，但新菜单中有的
            var addMenu = newMenuList.Where(a => !allMenu.Contains(a.Id)).ToList();


            
            if(deleMenu.Any())
            {
                var Dellist = (await _rolemenuRepository.GetQueryableAsync()).Where(a => a.RoleId == role.Id && deleMenu.Contains(a.MenuId)).ToList();
                await _rolemenuRepository.DeleteManyAsync(Dellist);
            }
            
            if(addMenu.Any())
            {
                var Addlist = new List<RoleMenu>();
                foreach (var menu in addMenu)
                {
                    Addlist.Add(new RoleMenu(GuidGenerator.Create())
                    {

                        RoleId = role.Id,
                        MenuId = menu.Id
                    });
                }
                await _rolemenuRepository.InsertManyAsync(Addlist);
            }                  
            
            return ResponseResult.Success("ok");
        }

        public async Task<ResponseResult<string>> CreateRole(CreateRoleInput input)
        {
            var role = await _roleRepository.FirstOrDefaultAsync(a => a.Name == input.Name);
            if (role != null)
            {
                throw new Exception($"角色名【{input.Name}】已存在");
            }
            if (input.Id.HasValue)
            {
                var editRole = await _roleRepository.FirstOrDefaultAsync(b => b.Id == input.Id);
                if (editRole == null)
                {
                    return ResponseResult<string>.Fail("记录不存在！");
                }

               editRole.ChangeName(input.Name);
                return ResponseResult<string>.Success("ok", input.Id.ToString());

            }
            else
            {
               
                var model = new IdentityRole(GuidGenerator.Create(), input.Name);
                model.SetProperty("CreationTime", DateTime.Now);
                model.SetProperty("CreationBy", CurrentUser.UserName);
                var result = await _roleRepository.InsertAsync(model, true);
                return ResponseResult<string>.Success("ok", result.Id.ToString());
            }
            

            
        }

        public async Task<ResponseResult> DeleteAsync(IdsInput<Guid> input)
        {
            var roles = await _roleRepository.GetListAsync(a => input.Ids.Contains(a.Id));

           foreach (var role in roles)
            {
                var userInRole = await _userManager.GetUsersInRoleAsync(role.Name);
                if (userInRole.Count>0)
                {
                    return ResponseResult.Fail($"角色名{role.Name}中关联有用户信息。");
                }
            }
           await _roleRepository.DeleteManyAsync(roles);

            return ResponseResult.Success("操作成功！");

        }

        public async Task<PageResponseResult<RoleOutput>> GetRoleList(GetRoleInput input)
        {
            var query =(await _roleRepository.GetQueryableAsync()).WhereIf(!string.IsNullOrEmpty(input.Name),a=>a.Name.Contains(input.Name));

            var totalCount = query.Count(); ;
            var list = await query.Skip(input.PageSize*input.PageIndex).Take(input.PageSize).ToListAsync();
            var dto = list.Adapt<List<RoleOutput>>();
            foreach (var item in dto)
            {
                var role = list.FirstOrDefault(a => a.Id == item.Id);
                var CreationTime =   role.GetProperty("CreationTime")?.ToString();
                if (string.IsNullOrEmpty(CreationTime))
                {
                    continue;
                }
                item.CreationTime = DateTime.Parse(CreationTime); 
                
            }
            return PageResponseResult<RoleOutput>.Success("ok", dto, input.PageSize,input.PageIndex,totalCount);
        }

        public async Task<ResponseResult> UpdateRole(UpdateRoleInput input)
        {
            var role =await _roleRepository.FirstOrDefaultAsync(a=>a.Name == input.Name);
            if(role == null)
            {
                return ResponseResult.Fail("角色不存在！");
            }


            //修改主表角色信息
            role.ChangeName(input.Name);
            await _roleManager.UpdateNormalizedRoleNameAsync(role);
            return ResponseResult.Success("操作成功！");
        }

        public async Task<ResponseResult<RoleOutput>> GetRoleInfo(Guid id)
        {
            var role = await _roleManager.GetByIdAsync(id);
            if(role == null)
            {
                return ResponseResult<RoleOutput>.Fail("记录不存在！");
            }

            var dto = role.Adapt<RoleOutput>();
            return ResponseResult<RoleOutput>.Success("操作成功", dto);
        }
    }
}
